package com.essence.grabiec104.grab.strategy;

import com.essence.common.model.Substation;
import com.essence.grabiec104.grab.dao.AlarmDao;
import com.essence.grabiec104.grab.model.AlarmRecord;
import com.essence.grabiec104.grab.model.AlarmRule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class ControlPointTotalStrategy extends AbstractSocketAlarmStrategy {
    
    @Autowired
    private AlarmDao alarmDao;

    public static final int ALARM_SCAN_FLAG_BIT = 1;

    @Override
    protected boolean doHandle(List<AlarmRule> rules) {
        // 过滤出控制帧总数类型的规则
        List<AlarmRule> rs = rules.stream()
                .filter(rule -> rule.getMetricTypeIndex() == AlarmRule.MetricTypeEnum.CONTROL_POINT_TOTAL.ordinal())
                .collect(Collectors.toList());
        if (rs.isEmpty()) {
            return false;
        }

        // 获取需要扫描的站点列表
        List<Substation> substations = alarmDao.getAllSubstation().stream()
                .filter(sub -> sub.isRtu() && (sub.getScanFlag() >> ALARM_SCAN_FLAG_BIT & 1L) == 0L)
                .collect(Collectors.toList());
        if (substations.isEmpty()) {
            return false;
        }

        // 过滤出需要扫描的规则
        List<AlarmRule> scanRules = rs.stream()
                .filter(rule ->
                        substations.stream()
                                .map(Substation::getId)
                                .anyMatch(id -> id == rule.getSubstation().getId())
                )
                .collect(Collectors.toList());
        if (scanRules.isEmpty()) {
            return false;
        }

        // 处理每个规则
        for (AlarmRule rule : scanRules) {
            long substationId = rule.getSubstation().getId();
            long startTime = System.currentTimeMillis() - rule.getIntervalSeconds() * 1000L;
            
            // 统计控制点总数
            int controlPointCount = alarmDao.countControlPointsInTimeRange(substationId, startTime);
            
            AlarmRecord existingAlarm = alarmDao.selectOpeningAlarmRecord(rule.getId(), substationId, 0);
            if (controlPointCount > rule.getThreshold()) {
                if (existingAlarm == null) {
                    // 新增告警记录
                    AlarmRecord ar = new AlarmRecord();
                    ar.setStatus(1); // 1表示告警中
                    ar.setAlarmRuleId(rule.getId());
                    ar.setStateId(substationId);
                    ar.setPointId(0); // 无特定点号
                    ar.setPacketId(0); // 无特定数据包
                    ar.setPointAddress(0); // 无特定地址
                    ar.setMaxThreshold(controlPointCount);
                    ar.setCreatedAt(System.currentTimeMillis());
                    ar.setUpdatedAt(System.currentTimeMillis());
                    ar.setSubstation(rule.getSubstation());
                    ar.setAlarmRule(rule);
                    alarmDao.insertAlarm(ar);
                    publish("append-alarm-record", List.of(ar));
                    log.info("告警类型: CONTROL_POINT_TOTAL(控制点总数) 新增告警记录");
                } else if (existingAlarm.getStatus() == 1 && controlPointCount > existingAlarm.getMaxThreshold()) {
                    existingAlarm.setMaxThreshold(controlPointCount);
                    existingAlarm.setUpdatedAt(System.currentTimeMillis());
                    existingAlarm.setSubstation(rule.getSubstation());
                    existingAlarm.setAlarmRule(rule);
                    alarmDao.updateAlarmById(existingAlarm);
                    publish("append-alarm-record", List.of(existingAlarm));
                    log.info("告警类型: CONTROL_POINT_TOTAL(控制点总数) 更新告警记录");
                }
            } else {
                if (existingAlarm != null && existingAlarm.getStatus() == 1) {
                    existingAlarm.setStatus(0);
                    existingAlarm.setUpdatedAt(System.currentTimeMillis());
                    existingAlarm.setSubstation(rule.getSubstation());
                    existingAlarm.setAlarmRule(rule);
                    alarmDao.updateAlarmById(existingAlarm);
                    publish("append-alarm-record", List.of(existingAlarm));
                }
                Substation sub = alarmDao.getSubstationById(substationId);
                long scanFlag = sub.getScanFlag() | (1L << ALARM_SCAN_FLAG_BIT);
                alarmDao.updateSubstationScanFlag(substationId, scanFlag);
                log.info("告警类型: CONTROL_POINT_TOTAL(控制点总数) 关闭告警记录");
            }
        }

        return true;
    }
}
